package crud.client;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
import com.smartgwt.client.types.TreeModelType;
import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeGridField;
import com.smartgwt.client.widgets.tree.TreeNode;

import crud.client.data.Colonne;
import crud.client.data.Table;
import crud.client.data.authentication.Right;
import crud.client.data.authentication.User;
import crud.client.dialog.AuthenticationDialog;
import crud.client.dialog.GenericTableCRUD;
import crud.client.event.AuthenticatedUserEvent;
import crud.client.service.ServiceLocator;
import crud.client.util.GenericCallback;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class NormasysCRUD implements EntryPoint
{
	private final Map<Table, GenericTableCRUD> tableCRUDMap = new HashMap<Table, GenericTableCRUD>();
	private HandlerManager handlerManager = new HandlerManager(this);
	private User user;

	public void onModuleLoad()
	{
		// HandlerManager des users
		getHandlerManager().addHandler(AuthenticatedUserEvent.getType(), new AuthenticatedUserEvent.AuthenticatedUserEventHandler()
		{
			public void onAuthenticatedUser(AuthenticatedUserEvent event)
			{
				if (event.getUser() != null)
				{
					setUser(event.getUser());
					buildWindow();
				}
			}
		});

		// User Authentifié par une tierce aplication
		GenericCallback<User> authenticatedUserCallback = new GenericCallback<User>()
		{
			@Override
			public void onSuccess(User authenticatedUser)
			{
				if (authenticatedUser != null)
				{
					handlerManager.fireEvent(new AuthenticatedUserEvent(authenticatedUser));
					// setUser(authenticatedUser);
					// buildWindow();
				} else
				{
					// User Authentifié par le CRUD
					GenericCallback<Boolean> authenticationRequiredCallback = new GenericCallback<Boolean>()
					{

						@Override
						public void onSuccess(Boolean authenticationRequired)
						{
							if (authenticationRequired == true)
							{
								@SuppressWarnings("unused")
								AuthenticationDialog authenticationDialog = new AuthenticationDialog(handlerManager);
							} else
							{
								buildWindow();
							}
						}
					};
					ServiceLocator.getServiceBase().authenticationRequired(authenticationRequiredCallback);
				}
			}
		};
		ServiceLocator.getServiceBase().getAuthenticatedUser(authenticatedUserCallback);
	}

	public void buildWindow()
	{
		// Les champs du TreeGrid
		final TreeGrid tree = new TreeGrid();

		// Affichage de l'arbre
		final TreeGridField arbreField = new TreeGridField("Table");
		CellFormatter cellFormatter = new CellFormatter()
		{
			public String format(Object value, ListGridRecord record, int rowNum, int colNum)
			{
				Object nodeValue = record.getAttributeAsObject("value");
				Table table = (Table) nodeValue;
				return table.getLibelle();
			}
		};

		arbreField.setCellFormatter(cellFormatter);

		tree.setHeight100();
		arbreField.setWidth(190);
		tree.setWidth(arbreField.getWidth());
		tree.setFields(arbreField);

		// Les données
		final Tree treeData = new Tree();

		treeData.setModelType(TreeModelType.PARENT);
		TreeNode root = new TreeNode();
		treeData.setRoot(root);

		tree.setData(treeData);

		GenericCallback<List<Table>> tableTreeCallback = new GenericCallback<List<Table>>()
		{

			@Override
			public void onSuccess(List<Table> tableList)
			{
				for (Table table : tableList)
				{
					Right right;
					if (user != null)
					{
						right = user.getAuthentication().getRight(table.getMappingClassName());
					} else
					{
						right = Right.MODIFICATION;
					}
					table.setRight(right);

					// Si il a un droit sur la table
					if (Right.NONE.equals(right) == false)
					{
						// Gestion des droits sur les tables
						TreeNode child = new TreeNode(table.getLibelle());
						child.setTitle(table.getLibelle());
						child.setAttribute("value", table);
						child.setAttribute("icon", "/img/table.png");

						treeData.add(child, treeData.getRoot());
					}
				}
			}
		};
		ServiceLocator.getServiceBase().getTableList(tableTreeCallback);

		RecordClickHandler selectionTableHandler = new RecordClickHandler()
		{

			@Override
			public void onRecordClick(RecordClickEvent event)
			{
				final TreeNode parent = (TreeNode) event.getRecord();

				Object nodeValue = parent.getAttributeAsObject("value");
				final Table table = (Table) nodeValue;

				if (tableCRUDMap.containsKey(table) == false || tableCRUDMap.get(table).isVisible() == false)
				{
					AsyncCallback<List<Colonne>> colonneListCallback = new GenericCallback<List<Colonne>>()
					{
						@Override
						public void onSuccess(List<Colonne> colonneList)
						{
							openTableCRUD(table, colonneList, tree.getLeft() + tree.getWidth() + 10, tree.getTop());
						}

					};
					ServiceLocator.getServiceBase().getColonneList(table, colonneListCallback);
				} else
				{
					// envoi au Top
					GenericTableCRUD tableCRUD = tableCRUDMap.get(table);
					tableCRUD.bringToFront();
					tableCRUD.focus();
				}
			}
		};
		tree.addRecordClickHandler(selectionTableHandler);

		RootPanel.get().add(tree);

	}

	public void openTableCRUD(final Table table, final List<Colonne> colonneList, int left, int top)
	{
		GenericTableCRUD tableCRUD = table.getWindowFactory().newWindow(table, colonneList);
		tableCRUD.initialize(this, left + (20 * tableCRUDMap.size()), top + 10 + (20 * tableCRUDMap.size()));
		tableCRUDMap.put(table, tableCRUD);
	}

	public void closeTableCRUD(Table table)
	{
		tableCRUDMap.remove(table);
	}

	public HandlerManager getHandlerManager()
	{
		return handlerManager;
	}

	public void setHandlerManager(HandlerManager handlerManager)
	{
		this.handlerManager = handlerManager;
	}

	public User getUser()
	{
		return user;
	}

	public void setUser(User user)
	{
		this.user = user;
	}

}
